﻿using System.Linq;
using CID.Domain.Development;
using CID.Tests.Support;
using NUnit.Framework;

namespace CID.Domain.Persistence.Tests.Development
{
    [TestFixture]
    class ComponentPersistenceTests : BasePersistenceWithDataTests
    {
        private static void AssertAreEqual(Component expected, Component actual)
        {
            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.Name, actual.Name);
            Assert.AreEqual(expected.Description, actual.Description);
            Assert.AreEqual(expected.Enabled, actual.Enabled);
            Assert.AreEqual(expected.Responsible.Id, actual.Responsible.Id);
            Assert.AreEqual(expected.RequiredServerRole.Id, actual.RequiredServerRole.Id);
            Assert.AreEqual(expected.ActivationDeactivationDefinition.Id, actual.ActivationDeactivationDefinition.Id);
            CollectionAssert.AreEquivalent(expected.Versions.Select(x => x.Id).ToArray(), actual.Versions.Select(x => x.Id).ToArray());
            CollectionAssert.AreEquivalent(expected.Dependants.Select(x => x.Id).ToArray(), actual.Dependants.Select(x => x.Id).ToArray());
        }

        [Test]
        public void PersistNewComponent_ComponentShouldBeSaved()
        {
            var session = OpenSession();
            var newComponent = DataProvider.CreateComponent(session, OperationsData.ServerRole1, UsersData.User1);
            session.SaveOrUpdate(newComponent);
            CleanSession(session);

            Assert.AreNotEqual(NotSavedId, newComponent.Id);
            session = OpenSession();
            var retrievedComponent = session.Get<Component>(newComponent.Id);
            AssertAreEqual(newComponent, retrievedComponent);
            CleanSession(session);
        }

        [Test]
        public void PersistModifiedComponent_ChangesShouldBeSaved()
        {
            var session = OpenSession();
            var newComponent = DataProvider.CreateComponent(session, OperationsData.ServerRole1, UsersData.User1);
            session.SaveOrUpdate(newComponent);
            CleanSession(session);

            session = OpenSession();
            var modifiedComponent = session.Get<Component>(newComponent.Id);
            AssertAreEqual(newComponent, modifiedComponent);//Necessary to get lazy collections before the session gets cleaned
            modifiedComponent.ModifyProperty(x => x.Name);
            modifiedComponent.ModifyProperty(x => x.Description);
            modifiedComponent.ModifyProperty(x => x.Enabled);
            modifiedComponent.Responsible = Users.DataProvider.GetUser(session, UsersData.User2);
            modifiedComponent.RequiredServerRole = Operations.DataProvider.GetServerRole(session, OperationsData.ServerRole2);
            session.SaveOrUpdate(modifiedComponent);
            CleanSession(session);

            session = OpenSession();
            var retrievedComponent = session.Get<Component>(newComponent.Id);
            AssertAreEqual(modifiedComponent, retrievedComponent);
            CleanSession(session);
        }

        [Test]
        public void DeleteComponent_ComponentShouldBeDeleted()
        {
            var session = OpenSession();
            var newComponent1 = DataProvider.CreateComponent(session, OperationsData.ServerRole1, UsersData.User1);
            session.SaveOrUpdate(newComponent1);
            var newComponent2 = DataProvider.CreateComponent(session, OperationsData.ServerRole2, UsersData.User2);
            session.SaveOrUpdate(newComponent2);
            CleanSession(session);

            session = OpenSession();
            var retrievedComponent1 = session.Get<Component>(newComponent1.Id);
            var retrievedComponent2 = session.Get<Component>(newComponent2.Id);
            session.Delete(retrievedComponent1);
            CleanSession(session);

            session = OpenSession();
            retrievedComponent1 = session.Get<Component>(newComponent1.Id);
            retrievedComponent2 = session.Get<Component>(newComponent2.Id);
            Assert.IsNull(retrievedComponent1);
            Assert.IsNotNull(retrievedComponent2);
            CleanSession(session);
        }
    }
}
